/*
 * @(#)Form.java
 * 2012-5-8 下午04:46:13
 * 
 * Copyright (c) 2018-2028, HangZhou QiYun InfoTech Co.,Ltd. .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qyxx.jwp.bean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;

import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.qyxx.jwp.datasource.TeAttr;

/**
 *  表单节点
 *  
 *  @author gxj
 *  @version 1.0 2012-5-8 下午04:46:13
 *  @since jdk1.6
 */
@XmlAccessorType(XmlAccessType.FIELD)
public class Form {
	
	/**
	 * 列表展现方式--普通列表
	 */
	public static final String LIST_TYPE_DATA_GRID = "DataGrid";
	
	/**
	 * 列表展现方式--树形列表
	 */
	public static final String LIST_TYPE_TREE_GRID = "TreeGrid";
	
	/**
	 * 列表展现方式--表单展现
	 */
	public static final String LIST_TYPE_FORM = "Form";
	
	/**
	 * 表单类型--库存
	 */
	public static final String FORM_TYPE_STOCK = "stock";
	
	/**
	 * 库存类型--出库
	 */
	public static final String STOCK_TYPE_OUT = "-1";
	
	/**
	 * 库存类型--入库
	 */
	public static final String STOCK_TYPE_IN = "1";
	
	/**
	 * 库存类型--出入库
	 */
	public static final String STOCK_TYPE_IN_OUT = "0";
	
	/**
	 * 库存类型--无
	 */
	public static final String STOCK_TYPE_NONE = "";
	
	/**
	 * 实体别名，用户hql语句生成
	 */
	public static final String[] ALIAS_ARRAY = new String[]{"a","b","c","d","e","f","g",
		"h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
    
	@XmlAttribute
	private String caption;
	@XmlAttribute
	private String key;
	@XmlAttribute
	private String tableName;
	@XmlAttribute
	private String languageText;
	@XmlAttribute
	private Boolean visible;
	@XmlAttribute
	private Boolean readOnly;
	@XmlAttribute
	private Integer cols;
	@XmlAttribute
	private Integer tabIndex;
	@XmlAttribute
	private Boolean isMaster; // 是否主表
	@JsonIgnoreProperties
	@XmlTransient
	private String entityName;
	@JsonIgnoreProperties
	@XmlTransient
	private String lcKey; //key首字母转小写
	
	@XmlElement(name="field")
	private List<Field> fieldList = new ArrayList<Field>();
	
	@XmlAttribute
	private Integer index;
	
	@XmlElement(name="query")
	private List<Query> queryList = new ArrayList<Query>();
	//是否虚拟表
	@XmlAttribute
	private Boolean isVirtual = false;
	
	@JsonIgnoreProperties
	@XmlTransient
	private String i18nKey;
	
	@XmlElement
	private Extension extension;
	
	@XmlAttribute
	private Boolean isListType = false;//是否列表显示

	@XmlAttribute
	private String listType = LIST_TYPE_DATA_GRID;
	
	@XmlAttribute
	private String treeField;
	
	@XmlAttribute
	private String visibleCondition;//字段是否可见条件
	/**
	 * 是否公用表
	 */
	@XmlAttribute
	private Boolean isCommon = false;
	
	/**
	 * 是否关联公用表
	 */
	@XmlAttribute
	private Boolean isReferCommon = false;
	
	/**
	 * 公用表类型--通用型、库存型等
	 */
	@XmlAttribute
	private String formType = "";
	
	/**
	 * 库存类型--出库、入库、出入库、无
	 */
	@XmlAttribute
	private String stockType = "";
	
	/**
	 * 出入库默认值--出库或入库
	 */
	@XmlAttribute
	private String inOutVal = STOCK_TYPE_OUT;
	
	/**
	 * 列表高度，子表使用
	 */
	@XmlAttribute
	private Integer height;
	
	/**
	 * 开启导入
	 */
	@XmlAttribute
	private Boolean enableImport = false;
	
	/**
	 * 开启导出
	 */
	@XmlAttribute
	private Boolean enableExport = false;
	
	/**
	 * 存放导出标签信息
	 */
	@XmlTransient
	private String tagInfo;
	
	/**
	 * 存放Foreach开始标签信息
	 */
	@XmlTransient
	private String forTagPrefixInfo;
	
	/**
	 * 存放Foreach结束标签信息
	 */
	@XmlTransient
	private String forTagSuffixInfo;
	
	/**
	 * 是否显示工具条
	 */
	@XmlAttribute
	private Boolean showTools = false;
	
	/**
	 * 动态展示：
	 * form为主表时，表示需要根据主表字段动态展示子表；
	 * form为子表时，表示需要根据主表字段动态显示某一个子表的字段；
	 */
	@XmlAttribute
	private Boolean dynamicShow = false;
	
	/**
	 * 开启字段权限检查
	 */
	@XmlAttribute
	private Boolean enableFieldAuthCheck = false;
	
	/**
	 * 自定义表单，关联模块查询
	 */
	@XmlAttribute
	private String referEntityTableName;
	
	/**
	 * 系统状态Tab页展示
	 */
	@XmlAttribute
	private Boolean showStatusInTab;
	
	/**
	 * 系统状态隐藏，默认不隐藏
	 */
	@XmlAttribute
	private Boolean isHideStatus = false;
	
	/**
	 * 列表显示记录数范围，如10,20,50,100
	 */
	@XmlAttribute
	private String pageSizeList;
	
	/**
	 * 列表显示一页默认记录数
	 */
	@XmlAttribute
	private String pageSize;
	
	/**
	 * 排序字段，如id,name
	 * 多个字段用逗号隔开
	 */
	@XmlAttribute
	private String sortName;
	
	/**
	 * 排序方式，如asc,desc
	 * 多个字段用逗号隔开
	 */
	@XmlAttribute
	private String sortOrder;
	
	/**
	 * 是否显示所有者
	 */
	@XmlAttribute
	private Boolean isShowCreateUser = true;
	
	/**
	 * 是否显示创建时间
	 */
	@XmlAttribute
	private Boolean isShowCreateTime = true;
	
	/**
	 * 是否显示最后修改者
	 */
	@XmlAttribute
	private Boolean isShowLastUpdateUser = false;
	
	/**
	 * 是否显示最后修改时间
	 */
	@XmlAttribute
	private Boolean isShowLastUpdateTime = false;
	
	/**
	 * 是否显示作废原因
	 */
	@XmlAttribute
	private Boolean isShowCancelReason = true;
	
	/**
	 * 开启分页选择模式
	 */
	@XmlAttribute
	private Boolean enablePageSelect = false;

	/**
	 * 是否excel导出
	 */
	@XmlElement(name="exportSystemField")
	private List<ExportSystemField> exportSystemFieldList;
	
	/**
	 * 查询框显示效果
	 */
	@XmlAttribute
	private String queryStyle = "leftshow";

	public String getQueryStyle() {
		return queryStyle;
	}

	public void setQueryStyle(String queryStyle) {
		this.queryStyle = queryStyle;
	}

	/**
	 * @return caption
	 */
	public String getCaption() {
		return caption;
	}


	
	/**
	 * @param caption
	 */
	public void setCaption(String caption) {
		this.caption = caption;
	}


	
	/**
	 * @return key
	 */
	public String getKey() {
		return key;
	}


	
	/**
	 * @param key
	 */
	public void setKey(String key) {
		this.key = key;
	}

	
	/**
	 * @return tableName
	 */
	public String getTableName() {
		return tableName;
	}



	
	/**
	 * @param tableName
	 */
	public void setTableName(String tableName) {
		this.tableName = tableName;
	}



	/**
	 * @return languageText
	 */
	public String getLanguageText() {
		return languageText;
	}


	
	/**
	 * @param languageText
	 */
	public void setLanguageText(String languageText) {
		this.languageText = languageText;
	}


	
	/**
	 * @return visible
	 */
	public Boolean getVisible() {
		return visible;
	}


	
	/**
	 * @param visible
	 */
	public void setVisible(Boolean visible) {
		this.visible = visible;
	}


	
	/**
	 * @return readOnly
	 */
	public Boolean getReadOnly() {
		return readOnly;
	}


	
	/**
	 * @param readOnly
	 */
	public void setReadOnly(Boolean readOnly) {
		this.readOnly = readOnly;
	}


	
	/**
	 * @return cols
	 */
	public Integer getCols() {
		return cols;
	}


	
	/**
	 * @param cols
	 */
	public void setCols(Integer cols) {
		this.cols = cols;
	}


	
	/**
	 * @return tabIndex
	 */
	public Integer getTabIndex() {
		return tabIndex;
	}


	
	/**
	 * @param tabIndex
	 */
	public void setTabIndex(Integer tabIndex) {
		this.tabIndex = tabIndex;
	}


	
	/**
	 * @return isMaster
	 */
	public Boolean getIsMaster() {
		return isMaster;
	}


	
	/**
	 * @param isMaster
	 */
	public void setIsMaster(Boolean isMaster) {
		this.isMaster = isMaster;
	}
	
	
	
	/**
	 * @return fieldList
	 */
	public List<Field> getFieldList() {
		return fieldList;
	}


	
	/**
	 * @param fieldList
	 */
	public void setFieldList(List<Field> fieldList) {
		this.fieldList = fieldList;
	}



	
	/**
	 * @return entityName
	 */
	public String getEntityName() {
		return entityName;
	}



	
	/**
	 * @param entityName
	 */
	public void setEntityName(String entityName) {
		this.entityName = entityName;
	}



	/**
	 * @return the lcKey
	 */
	public String getLcKey() {
		return lcKey;
	}



	/**
	 * @param lcKey the lcKey to set
	 */
	public void setLcKey(String lcKey) {
		this.lcKey = lcKey;
	}



	/**
	 * @return the index
	 */
	public Integer getIndex() {
		return index;
	}



	/**
	 * @param index the index to set
	 */
	public void setIndex(Integer index) {
		this.index = index;
	}



	
	/**
	 * @return queryList
	 */
	public List<Query> getQueryList() {
		return queryList;
	}



	
	/**
	 * @param queryList
	 */
	public void setQueryList(List<Query> queryList) {
		this.queryList = queryList;
	}
	
	/**
	 * @return isVirtual
	 */
	public Boolean getIsVirtual() {
		return isVirtual;
	}
	
	/**
	 * @param isVirtual
	 */
	public void setIsVirtual(Boolean isVirtual) {
		this.isVirtual = isVirtual;
	}



	
	/**
	 * @return i18nKey
	 */
	public String getI18nKey() {
		return i18nKey;
	}



	
	/**
	 * @param i18nKey
	 */
	public void setI18nKey(String i18nKey) {
		this.i18nKey = i18nKey;
	}



	
	/**
	 * @return extension
	 */
	public Extension getExtension() {
		return extension;
	}



	
	/**
	 * @param extension
	 */
	public void setExtension(Extension extension) {
		this.extension = extension;
	}



	
	/**
	 * @return listType
	 */
	public String getListType() {
		return listType;
	}



	
	/**
	 * @param listType
	 */
	public void setListType(String listType) {
		this.listType = listType;
	}



	
	/**
	 * @return treeField
	 */
	public String getTreeField() {
		return treeField;
	}



	
	/**
	 * @param treeField
	 */
	public void setTreeField(String treeField) {
		this.treeField = treeField;
	}



	
	/**
	 * @return isCommon
	 */
	public Boolean getIsCommon() {
		return isCommon;
	}



	
	/**
	 * @param isCommon
	 */
	public void setIsCommon(Boolean isCommon) {
		this.isCommon = isCommon;
	}



	
	/**
	 * @return isReferCommon
	 */
	public Boolean getIsReferCommon() {
		return isReferCommon;
	}



	
	/**
	 * @param isReferCommon
	 */
	public void setIsReferCommon(Boolean isReferCommon) {
		this.isReferCommon = isReferCommon;
	}
	
	
	
	
	/**
	 * @return formType
	 */
	public String getFormType() {
		return formType;
	}

	/**
	 * @param formType
	 */
	public void setFormType(String formType) {
		this.formType = formType;
	}


	/**
	 * @return stockType
	 */
	public String getStockType() {
		return stockType;
	}

	/**
	 * @param stockType
	 */
	public void setStockType(String stockType) {
		this.stockType = stockType;
	}

	
	/**
	 * @return inOutVal
	 */
	public String getInOutVal() {
		return inOutVal;
	}



	
	/**
	 * @param inOutVal
	 */
	public void setInOutVal(String inOutVal) {
		this.inOutVal = inOutVal;
	}


	/**
	 * @return height
	 */
	public Integer getHeight() {
		return height;
	}

	
	/**
	 * @param height
	 */
	public void setHeight(Integer height) {
		this.height = height;
	}


	/**
	 * @return enableImport
	 */
	public Boolean getEnableImport() {
		return enableImport;
	}

	
	/**
	 * @param enableImport
	 */
	public void setEnableImport(Boolean enableImport) {
		this.enableImport = enableImport;
	}

	
	/**
	 * @return enableExport
	 */
	public Boolean getEnableExport() {
		return enableExport;
	}



	
	/**
	 * @param enableExport
	 */
	public void setEnableExport(Boolean enableExport) {
		this.enableExport = enableExport;
	}

	
	/**
	 * @return tagInfo
	 */
	public String getTagInfo() {
		return tagInfo;
	}



	
	/**
	 * @param tagInfo
	 */
	public void setTagInfo(String tagInfo) {
		this.tagInfo = tagInfo;
	}
	
	
	/**
	 * @return forTagPrefixInfo
	 */
	public String getForTagPrefixInfo() {
		return forTagPrefixInfo;
	}



	
	/**
	 * @param forTagPrefixInfo
	 */
	public void setForTagPrefixInfo(String forTagPrefixInfo) {
		this.forTagPrefixInfo = forTagPrefixInfo;
	}



	
	/**
	 * @return forTagSuffixInfo
	 */
	public String getForTagSuffixInfo() {
		return forTagSuffixInfo;
	}



	
	/**
	 * @param forTagSuffixInfo
	 */
	public void setForTagSuffixInfo(String forTagSuffixInfo) {
		this.forTagSuffixInfo = forTagSuffixInfo;
	}
	/**
	 * @return visibleCondition
	 */
	public String getVisibleCondition() {
		return visibleCondition;
	}


	/**
	 * @param visibleCondition
	 */
	public void setVisibleCondition(String visibleCondition) {
		this.visibleCondition = visibleCondition;
	}
	
	/**
	 * @return showTools
	 */
	public Boolean getShowTools() {
		return showTools;
	}

	
	/**
	 * @param showTools
	 */
	public void setShowTools(Boolean showTools) {
		this.showTools = showTools;
	}

	/**
	 * @return dynamicShow
	 */
	public Boolean getDynamicShow() {
		return dynamicShow;
	}



	
	/**
	 * @param dynamicShow
	 */
	public void setDynamicShow(Boolean dynamicShow) {
		this.dynamicShow = dynamicShow;
	}

	/**
	 * @return enableFieldAuthCheck
	 */
	public Boolean getEnableFieldAuthCheck() {
		return enableFieldAuthCheck;
	}


	/**
	 * @param enableFieldAuthCheck
	 */
	public void setEnableFieldAuthCheck(Boolean enableFieldAuthCheck) {
		this.enableFieldAuthCheck = enableFieldAuthCheck;
	}

	
	public String getReferEntityTableName() {
		return referEntityTableName;
	}



	
	public void setReferEntityTableName(String referEntityTableName) {
		this.referEntityTableName = referEntityTableName;
	}


	
	public Boolean getIsListType() {
		return isListType;
	}



	
	public void setIsListType(Boolean isListType) {
		this.isListType = isListType;
	}


	/**
	 * @return showStatusInTab
	 */
	public Boolean getShowStatusInTab() {
		return showStatusInTab;
	}



	
	/**
	 * @param showStatusInTab
	 */
	public void setShowStatusInTab(Boolean showStatusInTab) {
		this.showStatusInTab = showStatusInTab;
	}

	/**
	 * @return isHideStatus
	 */
	public Boolean getIsHideStatus() {
		return isHideStatus;
	}

	/**
	 * @param isHideStatus
	 */
	public void setIsHideStatus(Boolean isHideStatus) {
		this.isHideStatus = isHideStatus;
	}


	/**
	 * @return pageSizeList
	 */
	public String getPageSizeList() {
		return pageSizeList;
	}


	/**
	 * @param pageSizeList
	 */
	public void setPageSizeList(String pageSizeList) {
		this.pageSizeList = pageSizeList;
	}



	
	/**
	 * @return pageSize
	 */
	public String getPageSize() {
		return pageSize;
	}

	
	/**
	 * @param pageSize
	 */
	public void setPageSize(String pageSize) {
		this.pageSize = pageSize;
	}

	
	/**
	 * @return sortName
	 */
	public String getSortName() {
		return sortName;
	}


	/**
	 * @param sortName
	 */
	public void setSortName(String sortName) {
		this.sortName = sortName;
	}

	
	/**
	 * @return sortOrder
	 */
	public String getSortOrder() {
		return sortOrder;
	}



	
	/**
	 * @param sortOrder
	 */
	public void setSortOrder(String sortOrder) {
		this.sortOrder = sortOrder;
	}

	
	/**
	 * @return isShowCreateUser
	 */
	public Boolean getIsShowCreateUser() {
		return isShowCreateUser;
	}



	
	/**
	 * @param isShowCreateUser
	 */
	public void setIsShowCreateUser(Boolean isShowCreateUser) {
		this.isShowCreateUser = isShowCreateUser;
	}



	
	/**
	 * @return isShowCreateTime
	 */
	public Boolean getIsShowCreateTime() {
		return isShowCreateTime;
	}



	
	/**
	 * @param isShowCreateTime
	 */
	public void setIsShowCreateTime(Boolean isShowCreateTime) {
		this.isShowCreateTime = isShowCreateTime;
	}



	
	/**
	 * @return isShowLastUpdateUser
	 */
	public Boolean getIsShowLastUpdateUser() {
		return isShowLastUpdateUser;
	}



	
	/**
	 * @param isShowLastUpdateUser
	 */
	public void setIsShowLastUpdateUser(Boolean isShowLastUpdateUser) {
		this.isShowLastUpdateUser = isShowLastUpdateUser;
	}



	
	/**
	 * @return isShowLastUpdateTime
	 */
	public Boolean getIsShowLastUpdateTime() {
		return isShowLastUpdateTime;
	}



	
	/**
	 * @param isShowLastUpdateTime
	 */
	public void setIsShowLastUpdateTime(Boolean isShowLastUpdateTime) {
		this.isShowLastUpdateTime = isShowLastUpdateTime;
	}



	
	/**
	 * @return isShowCancelReason
	 */
	public Boolean getIsShowCancelReason() {
		return isShowCancelReason;
	}



	
	/**
	 * @param isShowCancelReason
	 */
	public void setIsShowCancelReason(Boolean isShowCancelReason) {
		this.isShowCancelReason = isShowCancelReason;
	}

	
	/**
	 * @return enablePageSelect
	 */
	public Boolean getEnablePageSelect() {
		return enablePageSelect;
	}


	/**
	 * @param enablePageSelect
	 */
	public void setEnablePageSelect(Boolean enablePageSelect) {
		this.enablePageSelect = enablePageSelect;
	}
	
	/**
	 * 设置系统字段是否导出
	 * 
	 * @return
	 */
	public List<ExportSystemField> getExportSystemFieldList() {
		if(exportSystemFieldList == null) {
			//如果xml文件中还没有exportSystemFieldList字段，添加默认的字段
			exportSystemFieldList = new ArrayList<ExportSystemField>();
			List<TeAttr> teAttrList = getSystemFields();
			for(TeAttr ta : teAttrList) {
				ExportSystemField exportSystemField = new ExportSystemField();
				exportSystemField.setCaption(ta.getCaption());
				exportSystemField.setName(ta.getName());
				exportSystemField.setColumnName(ta.getColumnName());
				exportSystemField.setEnableExport(false);//默认不excel导出系统字段
				exportSystemFieldList.add(exportSystemField);
			}
		}
		return exportSystemFieldList;
	}

	public void setExportSystemFieldList(
			List<ExportSystemField> exportSystemFieldList) {
		this.exportSystemFieldList = exportSystemFieldList;
	}


	/**
	 * 获取系统字段
	 * 
	 * @return
	 */
	public List<TeAttr> getSystemFields() {
		List<TeAttr> sysAttrs = new ArrayList<TeAttr>();
		//id
		TeAttr ta = new TeAttr();
		ta.setName("id");
		ta.setCaption("编号");
		ta.setColumnName("ID");
		ta.setIsNotNull(true);
		ta.setIsUnique(true);
		ta.setType(DataProperties.DATA_TYPE_LONG);
		ta.setSize(38);
		ta.setScale(0);
		ta.setIsPrimaryKey(true);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//version
		ta = new TeAttr();
		ta.setName("version");
		ta.setCaption("版本号");
		ta.setColumnName("VERSION");
		ta.setIsNotNull(false);
		ta.setIsUnique(false);
		ta.setType(DataProperties.DATA_TYPE_LONG);
		ta.setSize(38);
		ta.setScale(0);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//createUser
		ta = new TeAttr();
		ta.setName("createUser");
		ta.setCaption("创建者");
		ta.setColumnName("CREATE_USER");
		ta.setIsNotNull(false);
		ta.setIsUnique(false);
		ta.setType(DataProperties.DATA_TYPE_LONG);
		ta.setSize(38);
		ta.setScale(0);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//createTime
		ta = new TeAttr();
		ta.setName("createTime");
		ta.setCaption("创建时间");
		ta.setColumnName("CREATE_TIME");
		ta.setIsNotNull(false);
		ta.setIsUnique(false);
		ta.setType(DataProperties.DATA_TYPE_DATETIME);
		ta.setSize(38);
		ta.setScale(0);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//lastUpdateUser
		ta = new TeAttr();
		ta.setName("lastUpdateUser");
		ta.setCaption("最后修改者");
		ta.setColumnName("LAST_UPDATE_USER");
		ta.setIsNotNull(false);
		ta.setIsUnique(false);
		ta.setType(DataProperties.DATA_TYPE_LONG);
		ta.setSize(38);
		ta.setScale(0);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//lastUpdateTime
		ta = new TeAttr();
		ta.setName("lastUpdateTime");
		ta.setCaption("最后修改时间");
		ta.setColumnName("LAST_UPDATE_TIME");
		ta.setIsNotNull(false);
		ta.setIsUnique(false);
		ta.setType(DataProperties.DATA_TYPE_DATETIME);
		ta.setSize(38);
		ta.setScale(0);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//status
		ta = new TeAttr();
		ta.setName("status");
		ta.setCaption("状态");
		ta.setColumnName("STATUS");
		ta.setIsNotNull(false);
		ta.setIsUnique(false);
		ta.setType(DataProperties.DATA_TYPE_STRING);
		ta.setSize(50);
		ta.setScale(0);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//sortOrderNo
		ta = new TeAttr();
		ta.setName("sortOrderNo");
		ta.setCaption("排序号");
		ta.setColumnName("SORT_ORDER_NO");
		ta.setIsNotNull(false);
		ta.setIsUnique(false);
		ta.setType(DataProperties.DATA_TYPE_LONG);
		ta.setSize(38);
		ta.setScale(0);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//atmId
		ta = new TeAttr();
		ta.setName("atmId");
		ta.setCaption("附件编号");
		ta.setColumnName("ATM_ID");
		ta.setIsNotNull(false);
		ta.setIsUnique(false);
		ta.setType(DataProperties.DATA_TYPE_LONG);
		ta.setSize(38);
		ta.setScale(0);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//flowInsId
		ta = new TeAttr();
		ta.setName("flowInsId");
		ta.setCaption("流程实例编号");
		ta.setColumnName("FLOW_INS_ID");
		ta.setIsNotNull(false);
		ta.setIsUnique(false);
		ta.setType(DataProperties.DATA_TYPE_STRING);
		ta.setSize(100);
		ta.setScale(0);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//cancelReason
		ta = new TeAttr();
		ta.setName("cancelReason");
		ta.setCaption("作废原因");
		ta.setColumnName("CANCEL_REASON");
		ta.setIsNotNull(false);
		ta.setIsUnique(false);
		ta.setType(DataProperties.DATA_TYPE_STRING);
		ta.setSize(500);
		ta.setScale(0);
		ta.setIsSystemAttr(true);
		sysAttrs.add(ta);
		//数据共享日志
		if(this.getIsMaster()) {
			ta = new TeAttr();
			ta.setName("dataShareLog");
			ta.setCaption("数据共享日志");
			ta.setColumnName("DATA_SHARE_LOG");
			ta.setIsNotNull(false);
			ta.setIsUnique(false);
			ta.setType(DataProperties.DATA_TYPE_MEMO);
			ta.setSize(1000);
			ta.setScale(0);
			ta.setIsSystemAttr(true);
			sysAttrs.add(ta);
		}
		/*//子表
		if(!this.getIsMaster()) {
			//masterId
			ta = new TeAttr();
			ta.setName("masterId");
			ta.setColumnName("MASTER_ID");
			ta.setIsNotNull(false);
			ta.setIsUnique(false);
			ta.setType(DataProperties.DATA_TYPE_LONG);
			ta.setSize(38);
			ta.setScale(0);
			ta.setIsSystemAttr(true);
			sysAttrs.add(ta);
		}*/
		//树形字段
		if(Form.LIST_TYPE_TREE_GRID.equals(this.getListType())) {
			//autoCode
			ta = new TeAttr();
			ta.setName("autoCode");
			ta.setCaption("编码");
			ta.setColumnName("AUTO_CODE");
			ta.setIsNotNull(false);
			ta.setIsUnique(false);
			ta.setType(DataProperties.DATA_TYPE_STRING);
			ta.setSize(200);
			ta.setScale(0);
			ta.setIsSystemAttr(true);
			sysAttrs.add(ta);
			//autoParentCode
			ta = new TeAttr();
			ta.setName("autoParentCode");
			ta.setCaption("父编码");
			ta.setColumnName("AUTO_PARENT_CODE");
			ta.setIsNotNull(false);
			ta.setIsUnique(false);
			ta.setType(DataProperties.DATA_TYPE_STRING);
			ta.setSize(200);
			ta.setScale(0);
			ta.setIsSystemAttr(true);
			sysAttrs.add(ta);
		}
		//公用表
		if(this.getIsCommon()) {
			//entityName
			ta = new TeAttr();
			ta.setName("entityName");
			ta.setCaption("模块名");
			ta.setColumnName("ENTITY_NAME");
			ta.setIsNotNull(false);
			ta.setIsUnique(false);
			ta.setType(DataProperties.DATA_TYPE_STRING);
			ta.setSize(200);
			ta.setScale(0);
			ta.setIsSystemAttr(true);
			sysAttrs.add(ta);
			//entityId
			ta = new TeAttr();
			ta.setName("entityId");
			ta.setCaption("模块ID");
			ta.setColumnName("ENTITY_ID");
			ta.setIsNotNull(false);
			ta.setIsUnique(false);
			ta.setType(DataProperties.DATA_TYPE_LONG);
			ta.setSize(38);
			ta.setScale(0);
			ta.setIsSystemAttr(true);
			sysAttrs.add(ta);
		}
		//库存表
		if(FORM_TYPE_STOCK.equals(this.getFormType())) {
			ta = new TeAttr();
			ta.setName("stockRatio");//库存系数
			ta.setCaption("库存系数");
			ta.setColumnName("STOCK_RATIO");
			ta.setIsNotNull(false);
			ta.setIsUnique(false);
			ta.setType(DataProperties.DATA_TYPE_LONG);
			ta.setSize(38);
			ta.setScale(0);
			ta.setIsSystemAttr(true);
			sysAttrs.add(ta);
		}
		return sysAttrs;
	}
	
	/**
	 * isReferCommon为true情况下，根据表字段属性，生成HQL语句
	 * 
	 * @return
	 */
	public String buildHql() {
		if(isReferCommon) {
			Map<String, List<Field>> entityMap = new HashMap<String, List<Field>>();
			//先将属性按不同实体归类
			for(Field field : fieldList) {
				if(null==field.getIsVirtual() || !field.getIsVirtual()) {
					//非虚拟字段
					if(StringUtils.isNotBlank(field.getKey())) {
						//属性名非空
						String eName = field.getEntityName();
						if(StringUtils.isBlank(eName)) {
							eName = this.entityName;
						}
						List<Field> fldList = entityMap.get(eName);
						if(null==fldList) {
							fldList = new ArrayList<Field>();
							entityMap.put(eName, fldList); 
						}
						fldList.add(field);
					}
				}
			}
			List<String> entityNameList = new ArrayList<String>();
			entityNameList.add(this.entityName);
			Set<String> enSet = entityMap.keySet();
			for(String en : enSet) {
				if(!en.equals(this.entityName)) {
					entityNameList.add(en);
				}
			}
			return buildSql(entityMap, entityNameList);
		} else {
			return buildCommonHql();
		}
	}
	
	/**
	 * 生成SQL语句，用于关联表查询
	 * 
	 * @param entityMap
	 * @param entityNameList
	 * @return
	 */
	public String buildSql(Map<String, List<Field>> entityMap, List<String> entityNameList) {
		StringBuffer sb = new StringBuffer("");
		StringBuffer selectSb = new StringBuffer();
		StringBuffer fromSb = new StringBuffer();
		StringBuffer joinSb = new StringBuffer();
		for(int i=0,len=entityNameList.size();i<len;i++) {
			String etName = entityNameList.get(i);
			String tbName = entityNameToTableName(etName);
			String alias = ALIAS_ARRAY[i+1];
			List<Field> flList = entityMap.get(etName);
			Boolean isExistSyncKey = false;//是否存在同步属性，存在需要进行自身关联
			if(null!=flList) {
				for(Field fd : flList) {
					selectSb.append(", ");
					if(StringUtils.isNotBlank(fd.getSyncKey())) {//拆分属性
						if(Form.STOCK_TYPE_IN_OUT.equals(this.getStockType())) {
							//出入库
							selectSb.append(alias);
							selectSb.append(".");
							selectSb.append(fd.getKey());
						} else {
							selectSb.append(alias);
							selectSb.append(".");
							String syncColName = "";
							for(Field f : flList){
								if(fd.getSyncKey().equals(f.getKey())) {
									syncColName = f.getDataProperties().getColName();
									break;
								}
							}
							selectSb.append(syncColName);
						}
						isExistSyncKey = true;
					} else {
						selectSb.append(alias);
						selectSb.append(".");
						selectSb.append(fd.getDataProperties().getColName());
					}
					selectSb.append(" as ");
					selectSb.append(fd.getKey());
				}
			}
			if(i==0) {
				fromSb.append(tbName);
				fromSb.append(" as ");
				fromSb.append(alias);

				//加入系统属性
				List<TeAttr> taList = this.getSystemFields();
				for(TeAttr ta : taList) {
					String key = ta.getName();
					selectSb.append(", ");
					selectSb.append(alias);
					selectSb.append(".");
					selectSb.append(ta.getColumnName());
					selectSb.append(" as ");
					selectSb.append(key);
				}
				if(!this.getIsMaster()) {
					//加入子表关联主表ID字段
					selectSb.append(", ");
					selectSb.append(alias);
					selectSb.append(".");
					selectSb.append("MASTER_ID");
					selectSb.append(" as ");
					selectSb.append("masterId");
				}
			
			} else {
				fromSb.append(" left join ");
				if(isExistSyncKey && Form.STOCK_TYPE_IN_OUT.equals(this.getStockType())) {
					//出入库
					String alias1 = ALIAS_ARRAY[i+1] + "1";
					String alias2 = ALIAS_ARRAY[i+1] + "2";
					StringBuffer inOutSelectSb = new StringBuffer();
					StringBuffer inOutJoinSb = new StringBuffer();
					for(Field fd : flList) {
						inOutSelectSb.append(", ");
						if(StringUtils.isNotBlank(fd.getSyncKey())) {//映射属性
							inOutSelectSb.append(alias2);
							inOutSelectSb.append(".");
							String syncColName = "";
							for(Field f : flList){
								if(fd.getSyncKey().equals(f.getKey())) {
									syncColName = f.getDataProperties().getColName();
									break;
								}
							}
							inOutSelectSb.append(syncColName);
							inOutSelectSb.append(" as ");
							inOutSelectSb.append(fd.getKey());
						} else {
							inOutSelectSb.append(alias1);
							inOutSelectSb.append(".");
							inOutSelectSb.append(fd.getDataProperties().getColName());
						}
					}
					inOutSelectSb.append(", ");
					inOutSelectSb.append(alias1);
					inOutSelectSb.append(".ENTITY_ID");
					inOutSelectSb.append(", ");
					inOutSelectSb.append(alias1);
					inOutSelectSb.append(".ENTITY_NAME");
					inOutJoinSb.append(tbName);
					inOutJoinSb.append(" as ");
					inOutJoinSb.append(alias1);
					inOutJoinSb.append(" left join ");
					inOutJoinSb.append(tbName);
					inOutJoinSb.append(" as ");
					inOutJoinSb.append(alias2);
					inOutJoinSb.append(" on ");
					inOutJoinSb.append(alias1);
					inOutJoinSb.append(".ENTITY_ID = ");
					inOutJoinSb.append(alias2);
					inOutJoinSb.append(".ENTITY_ID and ");
					inOutJoinSb.append(alias1);
					inOutJoinSb.append(".ENTITY_NAME = ");
					inOutJoinSb.append(alias2);
					inOutJoinSb.append(".ENTITY_NAME");
					inOutJoinSb.append(" where ");
					inOutJoinSb.append(alias1);
					inOutJoinSb.append(".ID <> ");
					inOutJoinSb.append(alias2);
					inOutJoinSb.append(".ID");
					inOutJoinSb.append(" and ");
					inOutJoinSb.append(alias1);
					inOutJoinSb.append(".STOCK_RATIO = ");
					if(STOCK_TYPE_OUT.equals(this.getInOutVal())) {
						inOutJoinSb.append(" -1 ");
					} else {
						inOutJoinSb.append(" 1 ");
					}
					inOutJoinSb.append(" and ");
					inOutJoinSb.append(alias2);
					inOutJoinSb.append(".STOCK_RATIO = ");
					if(STOCK_TYPE_OUT.equals(this.getInOutVal())) {
						inOutJoinSb.append(" 1 ");
					} else {
						inOutJoinSb.append(" -1 ");
					}
					
					inOutJoinSb.append(" and ");
					inOutJoinSb.append(alias1);
					inOutJoinSb.append(".ENTITY_NAME='");
					inOutJoinSb.append(this.entityName);
					inOutJoinSb.append("'");
					
					StringBuffer inOutSb = new StringBuffer();
					inOutSb.append("(select ");
					inOutSb.append(inOutSelectSb.toString().substring(1));
					inOutSb.append(" from ");
					inOutSb.append(inOutJoinSb.toString());
					inOutSb.append(")");
					fromSb.append(inOutSb.toString());
					fromSb.append(" as ");
					fromSb.append(alias);
					fromSb.append(" on ");
					fromSb.append(alias);
					fromSb.append(".ENTITY_ID = ");
					fromSb.append(ALIAS_ARRAY[1]);
					fromSb.append(".ID");
				} else {
					fromSb.append(tbName);
					fromSb.append(" as ");
					fromSb.append(alias);
					fromSb.append(" on ");
					fromSb.append(alias);
					fromSb.append(".ENTITY_ID = ");
					fromSb.append(ALIAS_ARRAY[1]);
					fromSb.append(".ID");
					fromSb.append(" and ");
					fromSb.append(alias);
					fromSb.append(".ENTITY_NAME='");
					fromSb.append(this.entityName);
					fromSb.append("'");
				}
			}
		}
		sb.append("select ");
		sb.append(ALIAS_ARRAY[0]);
		sb.append(".* from (");
		sb.append("select ");
		sb.append(selectSb.toString().substring(1));
		sb.append(" from ");
		sb.append(fromSb.toString());
		sb.append(" where 1=1 ");
		sb.append(joinSb.toString());
		sb.append(") as ");
		sb.append(ALIAS_ARRAY[0]);
		sb.append(" where 1=1 ");
		return sb.toString();
	}
	
	/**
	 * 生成HQL语句
	 * 
	 * @param entityMap
	 * @param entityNameList
	 * @return
	 */
	public String buildHql(Map<String, List<Field>> entityMap, List<String> entityNameList) {
		StringBuffer sb = new StringBuffer("");
		StringBuffer selectSb = new StringBuffer();
		StringBuffer fromSb = new StringBuffer();
		StringBuffer joinSb = new StringBuffer();
		for(int i=0,len=entityNameList.size();i<len;i++) {
			String etName = entityNameList.get(i);
			String alias = ALIAS_ARRAY[i];
			String alias1 = ALIAS_ARRAY[i] + "1";
			List<Field> flList = entityMap.get(etName);
			Boolean isExistSyncKey = false;//是否存在同步属性，存在需要进行自身关联
			if(null!=flList) {
				for(Field fd : flList) {
					selectSb.append(", ");
					if(StringUtils.isNotBlank(fd.getSyncKey())) {//映射属性
						if(Form.STOCK_TYPE_IN_OUT.equals(this.getStockType())) {
							//出入库
							selectSb.append(alias1);
							selectSb.append(".");
							selectSb.append(fd.getSyncKey());
						} else {
							selectSb.append(alias);
							selectSb.append(".");
							selectSb.append(fd.getSyncKey());
						}
						isExistSyncKey = true;
					} else {
						selectSb.append(alias);
						selectSb.append(".");
						selectSb.append(fd.getKey());
					}
					selectSb.append(" as ");
					selectSb.append(fd.getKey());
				}
			}
			if(i>0) {
				fromSb.append(",");
			}
			fromSb.append(etName);
			fromSb.append(" as ");
			fromSb.append(alias);
			if(isExistSyncKey && Form.STOCK_TYPE_IN_OUT.equals(this.getStockType())) {
				//出入库
				fromSb.append(",");
				fromSb.append(etName);
				fromSb.append(" as ");
				fromSb.append(alias1);
			}
			if(i>0) {
				joinSb.append(" and ");
				joinSb.append(alias);
				joinSb.append(".entityName='");
				joinSb.append(this.entityName);
				joinSb.append("' and ");
				joinSb.append(alias);
				joinSb.append(".entityId=");
				joinSb.append(ALIAS_ARRAY[0]);
				joinSb.append(".id ");
				if(isExistSyncKey && Form.STOCK_TYPE_IN_OUT.equals(this.getStockType())) {
					//出入库
					joinSb.append(" and ");
					joinSb.append(alias);
					joinSb.append(".entityName=");
					joinSb.append(alias1);
					joinSb.append(".entityName");
					joinSb.append(" and ");
					joinSb.append(alias);
					joinSb.append(".entityId=");
					joinSb.append(alias1);
					joinSb.append(".entityId");
					joinSb.append(" and ");
					joinSb.append(alias);
					joinSb.append(".id<>");
					joinSb.append(alias1);
					joinSb.append(".id");
				}
			} else {
				//加入系统属性
				List<TeAttr> taList = this.getSystemFields();
				for(TeAttr ta : taList) {
					String key = ta.getName();
					selectSb.append(", ");
					selectSb.append(alias);
					selectSb.append(".");
					selectSb.append(key);
					selectSb.append(" as ");
					selectSb.append(key);
				}
			}
		}
		sb.append("select ");
		sb.append(selectSb.toString().substring(1));
		sb.append(" from ");
		sb.append(fromSb.toString());
		sb.append(" where 1=1 ");
		sb.append(joinSb.toString());
		return sb.toString();
	}
	
	/**
	 * 生成单表HQL语句
	 * 
	 * @return
	 */
	public String buildCommonHql() {
		StringBuffer sb = new StringBuffer("");
		StringBuffer selectSb = new StringBuffer();
		StringBuffer fromSb = new StringBuffer();
		//自定义字段
		for(Field fd : this.fieldList) {
			if(StringUtils.isNotBlank(fd.getKey())) {
				selectSb.append(", ");
				selectSb.append(ALIAS_ARRAY[0]);
				selectSb.append(".");
				selectSb.append(fd.getKey());
				selectSb.append(" as ");
				selectSb.append(fd.getKey());
			}
		}
		//加入系统属性
		List<TeAttr> taList = this.getSystemFields();
		for(TeAttr ta : taList) {
			String key = ta.getName();
			selectSb.append(", ");
			selectSb.append(ALIAS_ARRAY[0]);
			selectSb.append(".");
			selectSb.append(key);
			selectSb.append(" as ");
			selectSb.append(key);
		}
		fromSb.append(this.entityName);
		fromSb.append(" as ");
		fromSb.append(ALIAS_ARRAY[0]);
		sb.append("select ");
		sb.append(selectSb.toString().substring(1));
		sb.append(" from ");
		sb.append(fromSb.toString());
		sb.append(" where 1=1 ");
		return sb.toString();
	}
	
	/**
	 * 将实体名转换为表名
	 * 
	 * @param entityName
	 * @return
	 */
	public static String entityNameToTableName(String entityName) {
		String[] ss = StringUtils.split(entityName, ".");
		return propertyToField(ss[1]);
	}
	
	/** 
     * 对象属性转换为字段，并转成大写  例如：userName to user_name 
     * @param property 字段名 
     * @return 
     */  
    public static String propertyToField(String property) {  
        if (null == property) {  
            return "";  
        }  
        char[] chars = property.toCharArray();  
        StringBuffer sb = new StringBuffer();  
        for (char c : chars) {  
            if (CharUtils.isAsciiAlphaUpper(c)) {  
                sb.append("_" + StringUtils.lowerCase(CharUtils.toString(c)));  
            } else {  
                sb.append(c);  
            }  
        }  
        return sb.toString().substring(1).toUpperCase();
    }  
	
	
}
